﻿using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.SystemUI;
using System.Windows.Forms;

namespace MyEngineExercise.我的扩展
{
    public class MapAndPageSync
    {
        /// <summary>
        /// MapAndPageSync实例
        /// </summary>
        private static MapAndPageSync _instance;
        /// <summary>
        /// 获取实例
        /// </summary>
        /// <returns></returns>
        public static MapAndPageSync Instance{get { return _instance; }}



        /// <summary>
        /// map控件实例
        /// </summary>
        private IMapControl3 _mapCtrl = null;
        /// <summary>
        /// map控件实例的属性
        /// </summary>
        public IMapControl3 MapControl
        {
            get { return _mapCtrl; }
            set { _mapCtrl = value; }
        }


        /// <summary>
        /// page控件的实例
        /// </summary>
        private IPageLayoutControl2 _pageCtrl = null;
        /// <summary>
        /// page控件的属性
        /// </summary>
        public IPageLayoutControl2 PageLayoutControl
        {
            get { return _pageCtrl; }
            set { _pageCtrl = value; }
        }


        /// <summary>
        /// toc控件的实例
        /// </summary>
        private readonly ITOCControl2 _tocCtrl = null;
        /// <summary>
        /// 获取TOC控件实例
        /// </summary>
        public ITOCControl2 TOCControl { get { return _tocCtrl; } }




        /// <summary>
        /// toolbar控件的实例
        /// </summary>
        private readonly IToolbarControl2 _toolbarCtrl = null;

        /// <summary>
        /// mainForm实例
        /// </summary>
        private readonly MainForm _mainForm = null;


        /// <summary>
        /// HookHelper实例
        /// </summary>
        private readonly HookHelper _hookHelper = null;
        /// <summary>
        /// 获取HookActions实例
        /// </summary>
        public IHookActions HookAction { get { return (IHookActions)_hookHelper; } }
        /// <summary>
        /// HookActions,如闪烁、zoom、pan等
        /// </summary>
        public IHookActions DoHookAction(Object unknow, esriHookActions action)
        {
            HookAction.DoAction(unknow,action);
            return HookAction;
        }


        /// <summary>
        /// 标记map是否处于活动状态
        /// </summary>
        private bool _isMapActived = false;

        /// <summary>
        /// 记录切换视图前，page正在激活的工具
        /// </summary>
        private ITool _pageLayoutActiveTool = null;

        /// <summary>
        /// 记录切换视图前，map正在激活的工具
        /// </summary>
        private ITool _mapActiveTool = null;


        /// <summary>
        /// 获取当前的活动视图
        /// </summary>
        public IActiveView ActiveView { get { return _isMapActived ? _mapCtrl.ActiveView : _pageCtrl.ActiveView; } }


        /// <summary>
        /// 获取当前焦点地图
        /// </summary>
        public IMap FocusMap { get { return ActiveView.FocusMap; } }

        /// <summary>
        /// 活动视图改变时的事件
        /// </summary>
        public event EventHandler<ActiveViewChangedEventArg> ActiveViewChanged = null;



        /// <summary>
        /// 创建MapAndPageSync实例
        /// </summary>
        /// <param name="mapCtrl"></param>
        /// <param name="pagCtrl"></param>
        /// <param name="tocCtrl"></param>
        /// <param name="toolbarCtrl"></param>
        /// <returns></returns>
        public static MapAndPageSync CreateInstance(
            IMapControl3 mapCtrl,
            IPageLayoutControl2 pageCtrl,
            ITOCControl2 tocCtrl,
            IToolbarControl2 toolbarCtrl,
            MainForm mainForm)
        {
            //如果实例为空，则创建实例
            if (null == _instance)
                _instance = new MapAndPageSync(mapCtrl, pageCtrl, tocCtrl, toolbarCtrl, mainForm);
            return _instance;
        }


        /// <summary>
        /// 私有构造函数
        /// </summary>
        /// <param name="mapCtrl"></param>
        /// <param name="pageCtrl"></param>
        /// <param name="tocCtrl"></param>
        /// <param name="toolbarCtrl"></param>
        private MapAndPageSync(
            IMapControl3 mapCtrl,
            IPageLayoutControl2 pageCtrl,
            ITOCControl2 tocCtrl,
            IToolbarControl2 toolbarCtrl,
            MainForm mainForm)
        {
            //初始化
            _mapCtrl = mapCtrl;
            _pageCtrl = pageCtrl;
            _tocCtrl = tocCtrl;
            _toolbarCtrl = toolbarCtrl;
            _mainForm = mainForm;

            _hookHelper = new HookHelperClass();
            _hookHelper.Hook = _mapCtrl.Object;

            _isMapActived = true;//默认激活map控件


            #region 初始化map和page的map(如果没有这个，创建mxd会出错！)
            //create a new instance of IMap
            IMap newMap = new MapClass();
            //create a new instance of IMaps collection which is needed by the PageLayout
            IMaps maps = new Maps();
            //add the new Map instance to the Maps collection
            maps.Add(newMap);
            //call replace map on the PageLayout in order to replace the focus map
            _pageCtrl.PageLayout.ReplaceMaps(maps);

            //assign the new map to the MapControl
            _mapCtrl.Map = newMap; 
            #endregion

            //设置默认坐标系
            _mapCtrl.SpatialReference = MyAeMethods.Instance.GetSpatialReference_Xian1980_3_38();

            //reset the active tools
            _mapActiveTool = null;
            _pageLayoutActiveTool = null;

            //make sure that the last active control is activated
            if (_isMapActived)
                this.ActivateMap();
            else
                this.ActivatePageLayout();
        }


        /// <summary>
        /// 激活map控件
        /// </summary>
        public void ActivateMap()
        {
            try
            {
                if (null == _mapCtrl || null == _pageCtrl)
                    throw new Exception("ControlsSynchronizer::ActivatePageLayout:\r\nEither MapControl or PageLayoutControl are not initialized!");

                //cache the current tool of the MapControl
                if (null != _pageCtrl.CurrentTool)
                    _pageLayoutActiveTool = _pageCtrl.CurrentTool;//记录切换之前，page正在使用的工具
                //deactivate the PagleLayout
                _pageCtrl.ActiveView.Deactivate();//使不可用

                //activate the MapControl
                _mapCtrl.ActiveView.Activate(_mapCtrl.hWnd);
                //assign the last active tool that has been used on the MapControl back as the active tool
                if (null != _mapActiveTool)
                    _mapCtrl.CurrentTool = _mapActiveTool;//获取map上一次使用的工具
                _isMapActived = true;
                //on each of the framework controls, set the Buddy control to the MapControl
                this.SetBuddies(_mapCtrl.Object);

                //触发事件
                if (null != this.ActiveViewChanged)
                    ActiveViewChanged(this, new ActiveViewChangedEventArg(_mapCtrl.ActiveView));
            }
            catch(Exception ex)
            {
                throw new Exception(string.Format("ControlsSynchronizer::ActivateMap:\r\n{0}",ex.Message));
            }
        }


        /// <summary>
        /// 激活page控件
        /// </summary>
        public void ActivatePageLayout()
        {
            try
            {
                if (null == _mapCtrl || null == _pageCtrl)
                    throw new Exception("ControlsSynchronizer::ActivatePageLayout:\r\nEither MapControl or PageLayoutControl are not initialized!");
                
                //cache the current tool of the MapControl
                if (null != _mapCtrl.CurrentTool)
                    _mapActiveTool = _mapCtrl.CurrentTool;//记录切换之前，map正在使用的工具
                //deactivate the PagleLayout
                _mapCtrl.ActiveView.Deactivate();//使不可用

                //activate the MapControl
                _pageCtrl.ActiveView.Activate(_pageCtrl.hWnd);//激活

                #region 缺少这句话会导致map和page切换时出现闪烁
                _pageCtrl.ActiveView.Activate(_pageCtrl.ActiveView.ScreenDisplay.hWnd);
                #endregion

                //assign the last active tool that has been used on the MapControl back as the active tool
                if (null != _pageLayoutActiveTool)
                    _pageCtrl.CurrentTool = _pageLayoutActiveTool;//获取page上一次使用的工具
                _isMapActived = false;
                //on each of the framework controls, set the Buddy control to the MapControl
                this.SetBuddies(_pageCtrl.Object);

                //触发事件
                if (null != ActiveViewChanged)
                    ActiveViewChanged(this,new ActiveViewChangedEventArg(_pageCtrl.ActiveView));

            }
            catch(Exception ex)
            {
                throw new Exception(string.Format("ControlsSynchronizer::ActivatePageLayout:\r\n{0}",ex.Message));
            }
        }


        /// <summary>
        /// 设置伙伴控件
        /// </summary>
        private void SetBuddies(object buddy)
        {
            try
            {
                if (null == buddy)
                    throw new Exception("ControlsSynchronizer::SetBuddies:\r\nTarget Buddy Control is not initialized!");

                _toolbarCtrl.SetBuddyControl(buddy);//设置toolbar伙伴控件
                _tocCtrl.SetBuddyControl(buddy);//设置toc伙伴控件
            }
            catch(Exception ex)
            {
                throw new Exception(string.Format("ControlsSynchronizer::SetBuddies:\r\n{0}",ex.Message));
            }
        }


        /// <summary>
        /// given a new map, replaces the PageLayoutControl and the MapControl's focus map
        /// 如果打开一个新的map，用该map替换PageLayoutControl和MapControl的焦点地图
        /// </summary>
        /// <param name="newMap"></param>
        public void ReplaceMap(IMap newMap)
        {
            if (null == newMap)
                throw new Exception("ControlsSynchronizer::ReplaceMap:\r\nNew map for replacement is not initialized!");

            if (null == _mapCtrl || null == _pageCtrl)
                throw new Exception("ControlsSynchronizer::ReplaceMap:\r\nEither MapControl or PageLayoutControl are not initialized!");

            //为什么要用这个？因为PageLayout的ReplaceMaps方法，要求IMaps类型的参数
            //create a new instance of IMaps collection which is needed by the PageLayout
            IMaps maps = new Maps();
            //add the new map to the Maps collection
            maps.Add(newMap);

            bool bIsMapActive = _isMapActived;//为什么要新建一个变量？因为这个变量在后面（激活map和激活page函数）会改变，这不是程序希望看到的

            //call replace map on the PageLayout in order to replace the focus map
            //we must call ActivatePageLayout, since it is the control we call 'ReplaceMaps'
            this.ActivatePageLayout();
            _pageCtrl.PageLayout.ReplaceMaps(maps);//用当前map替换掉PageLayout原来的maps

            //assign the new map to the MapControl
            _mapCtrl.Map = newMap;//替换map控件的map

            //reset the active tools
            _mapActiveTool = null;
            _pageLayoutActiveTool = null;

            //make sure that the last active control is activated
            //如果打开mxd文档前，activeview是map控件，则打开mxd文档后，设置activeview是map控件
            //同样如果打开mxd文档前，activeview是page控件，则打开mxd文档后，设置activeview是page控件
            if (bIsMapActive)
            {
                this.ActivateMap();
                _mapCtrl.ActiveView.Refresh();//刷新ActiveView
            }
            else
            {
                this.ActivatePageLayout();
                _pageCtrl.ActiveView.Refresh();//刷新ActiveView
            }
        }
    }
}
